import {defineStore} from 'pinia'
import {loginApi, logoutApi} from '@/api/system/user.api'
import {useBusinessCodeStore} from '@/stores/modules/businessCode.store'
import {cacheKeys} from '@/stores/constant/cacheKey'
import {clearSessionAndLocalStorage, Local, Session} from '@/utils/storageUtil'
import {resetAllStore} from '@/stores'
import {generateRoutes, removeAllDynamicRoutes} from '@/utils/routeUtil'
import {cloneDeep, pick} from 'lodash-es'
import {initialMenus} from '@/router/static'
import {useNavTabsStore} from '@/stores/modules/navTabs.store'
import {exist, treeArrayToArray} from '@/utils/commonUtil'
import {useWebConfigStore} from '@/stores/modules/webConfig.store'
import {i18n, loadLang} from '@/lang'
import type {MenuVO} from '@/model/route'
import type {UserVo} from '@/model/user-import'

/**
 * 选项式写法（相比于组合式写法，省去了return所有变量和方法）
 */
export const useUserStore = defineStore(cacheKeys.USER, {
	state(): {
		email: UserVo['email'],
		avatar: UserVo['avatar'],
		gender: UserVo['gender'],
		introduction: UserVo['introduction'],
		nickname: UserVo['nickname'],
		username: UserVo['username'],
		userId: UserVo['userId'],
		emailNotifyTypes: UserVo['emailNotifyTypes'],
		roleCodes: UserVo['roleCodes'],
		roleNames: UserVo['roleNames'],
		isAdmin?: UserVo['isAdmin'],
		lastModifyUsernameDate?: UserVo['lastModifyUsernameDate'],
		lastModifyNicknameDate?: UserVo['lastModifyNicknameDate'],
		dynamicMenus: UserVo['dynamicMenus'],
		menus: UserVo['menus'],
		buttons: UserVo['buttons'],
		loginCallback?: () => void,
		logoutCallback?: () => void
	} {
		return {
			email: undefined,
			avatar: undefined,
			gender: undefined,
			introduction: undefined,
			nickname: undefined,
			username: undefined,
			userId: undefined,
			emailNotifyTypes: [],
			roleCodes: [],
			roleNames: [],
			isAdmin: undefined,
			lastModifyUsernameDate: undefined,
			lastModifyNicknameDate: undefined,
			dynamicMenus: [],
			menus: [],
			buttons: [],
			loginCallback: undefined,
			logoutCallback: undefined
		}
	},
	getters: {
		watermark(state) {
			if (Local.get(cacheKeys.TOKEN)) {
				const content: string[] = []
				if (this.nickname) {
					content.push(this.nickname)
				}
				if (this.username) {
					content.push(this.username)
				}
				return content
			} else {
				return []
			}
		}
	},
	actions: {
		modifyToken(newToken?: UserVo['token'], newExpire?: UserVo['expire']) {
			if (newToken) {
				Local.set(cacheKeys.TOKEN, newToken)
			}
			if (newExpire) {
				Local.set(cacheKeys.EXPIRE, newExpire)
			}
		},
		modifyUserInfo(newUser?: SysUser) {
			if (newUser) {
				this.nickname = newUser.nickname
				this.username = newUser.username
				this.email = newUser.email
				this.avatar = newUser.avatar
				this.gender = newUser.gender
				this.emailNotifyTypes = newUser.emailNotifyTypes || []
				this.introduction = newUser.introduction
				this.lastModifyUsernameDate = newUser.lastModifyUsernameDate
				this.lastModifyNicknameDate = newUser.lastModifyNicknameDate
			}
		},
		/**
		 * 根据静态路由和动态路由生成全部菜单数据
		 */
		generateMenu() {
			let allMenus: MenuVO[] = <MenuVO[]><unknown>cloneDeep(initialMenus)
			allMenus = allMenus.concat(this.dynamicMenus || [])
			this.menus = allMenus
		},
		async login(loginForm: LoginForm) {
			const data = (await loginApi(loginForm)).data
			Local.set(cacheKeys.TOKEN, data.token)
			Local.set(cacheKeys.EXPIRE, data.expire)
			this.userId = data.userId
			this.username = data.username
			this.nickname = data.nickname
			this.email = data.email
			this.avatar = data.avatar
			this.gender = data.gender
			this.introduction = data.introduction
			this.emailNotifyTypes = data.emailNotifyTypes
			this.roleCodes = data.roleCodes
			this.roleNames = data.roleNames
			this.isAdmin = data.isAdmin
			this.lastModifyUsernameDate = data.lastModifyUsernameDate
			this.lastModifyNicknameDate = data.lastModifyNicknameDate
			this.dynamicMenus = data.menus && data.menus.length > 0 ? data.menus : []
			this.buttons = data.buttons && data.buttons.length > 0 ? data.buttons : []
			// 加载动态路由
			generateRoutes()
			// 初始化菜单
			this.generateMenu()
			// 初始化固定tab
			const navTabsStore = useNavTabsStore()
			navTabsStore.openedTabs = []
			for (const menu of treeArrayToArray(this.menus)) {
				if (menu.meta.affix) {
					navTabsStore.openedTabs.push(menu)
				}
			}
			// 获取业务编码
			await useBusinessCodeStore().fetchBusinessCodes()
			// 应用用户的网站配置
			const userWebConfig: WebConfig = data.webConfig
			if (userWebConfig) {
				const webConfigStore = useWebConfigStore()
				this.loginCallback = () => {
					// 布局配置
					const userWebConfigPick = pick(userWebConfig, Object.keys(webConfigStore.layout))
					for (const key in userWebConfigPick) {
						if (exist(userWebConfigPick[<keyof WebConfig>key])) {
							(<LayoutConfig & AnyObject>webConfigStore.layout)[key] = userWebConfigPick[<keyof WebConfig>key]
						}
					}
					Session.set(cacheKeys.BEFORE_RESIZE_LAYOUT, {
						layoutMode: webConfigStore.layout.layoutMode,
						menuCollapse: webConfigStore.layout.menuCollapse
					})
					// 语言配置
					if (exist(userWebConfig.language) && i18n.global.locale.value !== userWebConfig.language) {
						loadLang(userWebConfig.language!)
					}
				}
			}
		},
		async logout() {
			await logoutApi()
			this.logoutCallback = () => {
				this.clearAllUserInfo()
				if (i18n.global.locale.value !== 'zh-cn') {
					loadLang('zh-cn')
				}
			}
		},
		clearAllUserInfo() {
			// 清除pinia中的数据
			resetAllStore()
			// 清除sessionStorage、localStorage中项目相关的的数据
			clearSessionAndLocalStorage()
			// 删除动态路由，只保留静态路由
			removeAllDynamicRoutes()
		},
		resetUserStore() {
			this.userId = undefined
			this.username = undefined
			this.nickname = undefined
			this.email = undefined
			this.avatar = undefined
			this.gender = undefined
			this.introduction = undefined
			this.emailNotifyTypes.length = 0
			this.roleCodes.length = 0
			this.roleNames.length = 0
			this.isAdmin = undefined
			this.lastModifyUsernameDate = undefined
			this.lastModifyNicknameDate = undefined
			this.dynamicMenus.length = 0
			this.menus.length = 0
			this.buttons.length = 0
		}
	},
	persist: {
		key: cacheKeys.USER,
		storage: window.localStorage
	}
})
